home *** CD-ROM | disk | FTP | other *** search
/ Sun Solutions 1997 April to September / Sun Solutions CD - APR '97 - SEP '97 (704-3778-12 Rev. H)(Sun Microsystems, Inc.)(1997).iso / products / Hyperion / src / plat_news.c < prev    next >
C/C++ Source or Header  |  1997-02-26  |  7KB  |  403 lines

  1. /*
  2.  * @(#)plat_news.c    1.5    1/1/94
  3.  *
  4.  * Sony NEWS-specific drive control routines.
  5.  */
  6. static char *ident = "@(#)plat_news.c    1.5 1/1/94";
  7.  
  8. #ifdef __sony_news
  9.  
  10. #include <errno.h>
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #include <fcntl.h>
  14. #include <sys/param.h>
  15. #include <sys/stat.h>
  16. #include <sys/time.h>
  17. #include <ustat.h>
  18. #include <CD.h>
  19.  
  20. #define    DEFAULT_CD_DEVICE    "/dev/rsd/b0i6u0p2\0"
  21.  
  22. #include "struct.h"
  23.  
  24. void *malloc();
  25. char *strchr();
  26.  
  27. extern char    *cd_device;
  28. extern int    intermittent_dev;
  29.  
  30. int    min_volume = 128;
  31. int    max_volume = 255;
  32.  
  33. /*
  34.  * Initialize the drive.  A no-op for the generic driver.
  35.  */
  36. int
  37. gen_init(d)
  38.     struct wm_drive    *d;
  39. {
  40.     return (0);
  41. }
  42.  
  43. /*
  44.  * Get the number of tracks on the CD.
  45.  */
  46. int
  47. gen_get_trackcount(d, tracks)
  48.     struct wm_drive    *d;
  49.     int        *tracks;
  50. {
  51.     struct CD_Capacity    cc;
  52.  
  53.     if (CD_GetCapacity(d->fd, &cc))
  54.         return (-1);
  55.  
  56.     *tracks = cc.etrack - 1;
  57.     return (0);
  58. }
  59.  
  60. /*
  61.  * Get the start time and mode (data or audio) of a track.
  62.  */
  63. int
  64. gen_get_trackinfo(d, track, data, startframe)
  65.     struct wm_drive    *d;
  66.     int        track, *data, *startframe;
  67. {
  68.     struct CD_TOCinfo    hdr;
  69.     struct CD_TOCdata    ent;
  70.  
  71.     hdr.strack = track;
  72.     hdr.ntrack = 1;
  73.     hdr.data = &ent;
  74.     if (CD_ReadTOC(d->fd, &hdr))
  75.         return (-1);
  76.  
  77.     *data = (ent.control & 4) ? 1 : 0;
  78.     *startframe = ent.baddr;
  79.  
  80.     return (0);
  81. }
  82.  
  83. /*
  84.  * Get the number of frames on the CD.
  85.  */
  86. int
  87. gen_get_cdlen(d, frames)
  88.     struct wm_drive    *d;
  89.     int        *frames;
  90. {
  91.     int        tmp;
  92.  
  93.     if ((d->get_trackcount)(d, &tmp))
  94.         return (-1);
  95.  
  96.     return (gen_get_trackinfo(d, tmp + 1, &tmp, frames));
  97. }
  98.  
  99. /*
  100.  * Get the current status of the drive: the current play mode, the absolute
  101.  * position from start of disc (in frames), and the current track and index
  102.  * numbers if the CD is playing or paused.
  103.  */
  104. int
  105. gen_get_drive_status(d, oldmode, mode, pos, track, index)
  106.     struct wm_drive    *d;
  107.     enum cd_modes    oldmode, *mode;
  108.     int        *pos, *track, *index;
  109. {
  110.     struct CD_Status        sc;
  111.  
  112.     /* If we can't get status, the CD is ejected, so default to that. */
  113.     *mode = EJECTED;
  114.  
  115.     /* Is the device open? */
  116.     if (d->fd < 0)
  117.     {
  118.         switch (wmcd_open(d)) {
  119.         case -1:    /* error */
  120.             return (-1);
  121.  
  122.         case 1:        /* retry */
  123.             return (0);
  124.         }
  125.     }
  126.  
  127.     /* Disc is ejected.  Close the device. */
  128.     if (CD_GetStatus(d->fd, &sc))
  129.     {
  130.         WMclose(d->fd);
  131.         d->fd = -1;
  132.         return (0);
  133.     }
  134.  
  135.     switch (sc.status) {
  136.     case CDSTAT_PLAY:
  137.         *mode = PLAYING;
  138.         *track = sc.tno;
  139.         *index = sc.index;
  140.         *pos = sc.baddr;
  141.         break;
  142.  
  143.     case CDSTAT_PAUSE:
  144.         if (oldmode == PLAYING || oldmode == PAUSED)
  145.         {
  146.             *mode = PAUSED;
  147.             *track = sc.tno;
  148.             *index = sc.index;
  149.             *pos = sc.baddr;
  150.         }
  151.         else
  152.             *mode = STOPPED;
  153.         break;
  154.  
  155.     case CDSTAT_STOP:
  156.         if (oldmode == PLAYING)
  157.         {
  158.             *mode = TRACK_DONE;    /* waiting for next track. */
  159.             break;
  160.         }
  161.         /* fall through */
  162.  
  163.     default:
  164.         *mode = STOPPED;
  165.         break;
  166.     }
  167.  
  168.     return (0);
  169. }
  170.  
  171. /*
  172.  * Set the volume level for the left and right channels.  Their values
  173.  * range from 0 to 100.
  174.  */
  175. int
  176. gen_set_volume(d, left, right)
  177.     struct wm_drive    *d;
  178.     int        left, right;
  179. {
  180.     /* NEWS can't adjust volume! */
  181.     return (0);
  182. }
  183.  
  184. /*
  185.  * Pause the CD.
  186.  */
  187. int
  188. gen_pause(d)
  189.     struct wm_drive    *d;
  190. {
  191.     CD_Pause(d->fd);
  192.  
  193.     return (0);
  194. }
  195.  
  196. /*
  197.  * Resume playing the CD (assuming it was paused.)
  198.  */
  199. int
  200. gen_resume(d)
  201.     struct wm_drive    *d;
  202. {
  203.     CD_Restart(d->fd);
  204.  
  205.     return (0);
  206. }
  207.  
  208. /*
  209.  * Stop the CD.
  210.  */
  211. int
  212. gen_stop(d)
  213.     struct wm_drive *d;
  214. {
  215.     CD_Stop(d->fd);
  216.  
  217.     return (0);
  218. }
  219.  
  220. /*
  221.  * Play the CD from one position to another (both in frames.)
  222.  */
  223. int
  224. gen_play(d, start, end)
  225.     struct wm_drive    *d;
  226.     int        start, end;
  227. {
  228.     struct CD_PlayAddr        msf;
  229.  
  230.     msf.addrmode            = CD_MSF;
  231.     msf.addr.msf.startmsf.min    = start / (60*75);
  232.     msf.addr.msf.startmsf.sec    = (start % (60*75)) / 75;
  233.     msf.addr.msf.startmsf.frame    = start % 75;
  234.     msf.addr.msf.endmsf.min        = end / (60*75);
  235.     msf.addr.msf.endmsf.sec        = (end % (60*75)) / 75;
  236.     msf.addr.msf.endmsf.frame    = end % 75;
  237.  
  238.     if (CD_Play(d->fd, &msf))
  239.     {
  240.         printf("play_chunk(%d,%d)\n",start,end);
  241.         printf("msf = %d:%d:%d %d:%d:%d\n",
  242.             msf.addr.msf.startmsf.min,
  243.             msf.addr.msf.startmsf.sec,
  244.             msf.addr.msf.startmsf.frame,
  245.             msf.addr.msf.endmsf.min,
  246.             msf.addr.msf.endmsf.sec,
  247.             msf.addr.msf.endmsf.frame);
  248.         perror("CD_Play");
  249.         return (-1);
  250.     }
  251.  
  252.     return (0);
  253. }
  254.  
  255. /*
  256.  * Eject the current CD, if there is one.
  257.  */
  258. int
  259. gen_eject(d)
  260.     struct wm_drive    *d;
  261. {
  262.     struct stat    stbuf;
  263.     struct ustat    ust;
  264.  
  265.     if (fstat(d->fd, &stbuf) != 0)
  266.         return (-2);
  267.  
  268.     /* Is this a mounted filesystem? */
  269.     if (ustat(stbuf.st_rdev, &ust) == 0)
  270.         return (-3);
  271.  
  272.     if (CD_AutoEject(d->fd))
  273.         return (-1);
  274.  
  275.     /* Close the device if it needs to vanish. */
  276.     if (intermittent_dev)
  277.     {
  278.         WMclose(d->fd);
  279.         d->fd = -1;
  280.     }
  281.  
  282.     return (0);
  283. }
  284.  
  285. /*
  286.  * Close the CD device.
  287.  */
  288. int
  289. WMclose(fd)
  290.     int    fd;
  291. {
  292.     int    ret;
  293.  
  294.     ret = CD_Close(fd);
  295.     susleep(3000000);
  296.     return (ret);
  297. }
  298.  
  299. /*
  300.  * Read the initial volume from the drive, if available.  Each channel
  301.  * ranges from 0 to 100, with -1 indicating data not available.
  302.  */
  303. int
  304. gen_get_volume(d, left, right)
  305.     struct wm_drive    *d;
  306.     int        *left, *right;
  307. {
  308.     /* Suns, HPs, Linux, NEWS can't read the volume; oh well */
  309.     *left = *right = -1;
  310.  
  311.     return (0);
  312. }
  313.  
  314. /*
  315.  * Pass SCSI commands to the device.
  316.  */
  317. int
  318. wm_scsi(d, cdb, cdblen, buf, buflen, getreply)
  319.     struct wm_drive    *d;
  320.     unsigned char    *cdb, *buf;
  321.     int        cdblen, buflen, getreply;
  322. {
  323.     /* NEWS can't do SCSI passthrough... or can it? */
  324.     return (-1);
  325. }
  326.  
  327. /*
  328.  * Open the CD device and figure out what kind of drive is attached.
  329.  */
  330. int
  331. wmcd_open(d)
  332.     struct wm_drive    *d;
  333. {
  334.     int        fd;
  335.     static int    warned = 0;
  336.     char        vendor[9], model[17], rev[5];
  337.  
  338.     if (d->fd >= 0)        /* Device already open? */
  339.         return (0);
  340.  
  341.     intermittent_dev = 1;
  342.     if (cd_device == NULL)
  343.         cd_device = DEFAULT_CD_DEVICE;
  344.  
  345.     if ((d->fd = CD_Open(cd_device, 0)) < 0)
  346.     {
  347.         /* Solaris 2.2 volume manager moves links around */
  348.         if (errno == ENOENT && intermittent_dev)
  349.             return (0);
  350.  
  351.         if (errno == EACCES)
  352.         {
  353.             if (!warned)
  354.             {
  355.                 char    realname[MAXPATHLEN];
  356.  
  357.                 if (realpath(cd_device, realname) == NULL)
  358.                 {
  359.                     perror("realpath");
  360.                     return (0);
  361.                 }
  362.  
  363.                 fprintf(stderr,
  364.         "As root, please run\n\nchmod 666 %s\n\n%s\n", realname,
  365.         "to give yourself permission to access the CD-ROM device.");
  366.                 warned++;
  367.             }
  368.         }
  369.         else if (errno != EIO)    /* defined at top */
  370.         {
  371.             perror(cd_device);
  372.             exit(1);
  373.         }
  374.  
  375.         /* No CD in drive. */
  376.         return (1);
  377.     }
  378.  
  379.     if (warned)
  380.     {
  381.         warned = 0;
  382.         fprintf(stderr, "Thank you.\n");
  383.     }
  384.  
  385.     /* Now fill in the relevant parts of the wm_drive structure. */
  386.     fd = d->fd;
  387.  
  388.     /* Figure out the drive type, if possible */
  389.     vendor[0] = model[0] = rev[0] = '\0';
  390.     wm_scsi_get_drive_type(d, vendor, model, rev);
  391.     *d = *(find_drive_struct(vendor, model, rev));
  392.     d->fd = fd;
  393.  
  394.     (d->init)(d);
  395.  
  396.     return (0);
  397. }
  398.  
  399. void
  400. keep_cd_open() { }
  401.  
  402. #endif
  403.